import java.util.*;
import java.io.*;
import java.lang.*;

class PackText
{
	static final String PACK_NAME = "packName";
	static final String PACK_FILE = "packFile";
	
	static String[][] files = new String[20][20];
	static String[] packageNames = new String[20];
	static int nbPack = -1;
	static int[] nbFileEachPack = new int[20];
	
	static String iniFile = "";
	static String inDir = "";
	static String outDir = "";
	
	static int offset = 0;
	
	// --- LOG
    static void LOG(String a)
    {
        System.out.println(a);
    }
            
    // --- ERR
    static void ERR(String a)
    {
    	System.err.println("ERR::"+a);
    }
	
	static int Read32(byte[] data) 
	{
		return (int)((data[offset++]&0xFF) 
					| ((data[offset++]&0xFF)<<8) 
					| ((data[offset++]&0xFF)<<16) 
					| ((data[offset++]&0xFF)<<24)
					);
	}
	static String getFilePath(String filename) throws Exception
	{
		int i;
		if ( (i = filename.lastIndexOf('\\')) != -1) 
		{
			return filename.substring(0, i) + "\\";

		} 
		else if ( (i = filename.lastIndexOf('/')) != -1) 
		{
			filename = filename.substring(0, i) + "/";
			filename = filename.replaceAll("\\", "/");
			return filename;
		}
		else 
		{
			return ".\\";
		}
	}
	static void Write32(FileOutputStream out, int value) throws Exception
	{
		byte [] b = new byte[4];
		b[0] = (byte)(value & 0xFF);
		b[1] = (byte)((value >> 8) & 0xFF);
		b[2] = (byte)((value >> 16) & 0xFF);
		b[3] = (byte)((value >> 24) & 0xFF);
		out.write(b, 0, 4);
	}
	static boolean LoadPack(String pack)
	{
		System.out.println(">>>> LoadPack()");
		byte[] _buffer = null;
		int size = 0;
		int nbString = 0;
		int nbPart = 0;
		int[] stringsOffset = null;

		try
		{
			FileInputStream file = new FileInputStream(pack);
			size = file.available();
			_buffer = new byte[size];
			file.read(_buffer);
		}
		catch(Exception ex)
		{
			System.err.println(ex.toString());
			return false;
		}
		nbPart = Read32(_buffer);
		System.out.println(">>>> nbPart: "+nbPart);
		byte[][] partBuffer = new byte[nbPart][];
		int partSize = 0;
		for(int i=0; i<nbPart; i++)
		{
			partSize = Read32(_buffer);
			if(partSize < 0)
				return false;
			partBuffer[i] = new byte[partSize];
			System.arraycopy(_buffer, offset, partBuffer[i], 0, partSize);
			offset += partSize;
			System.out.println("	Part "+(i+1)+": "+partSize+"bytes");
		}
		

		return true;
	}
	static boolean LoadInfo()
	{
		try
		{
			FileInputStream fstream = new FileInputStream(iniFile);
			BufferedReader reader = new BufferedReader(new InputStreamReader(fstream));
			
			String strLine;
			int k = -1;
			String strFirst, strLast;
			int nbFile = 0;
			while((strLine = reader.readLine()) != null)
			{
				// LOG("readLine="+strLine);
				strLine = strLine.trim();
				k = strLine.indexOf("//");
				if(k>-1)
					strLine = strLine.substring(0,k).trim();
				if(strLine.length() == 0)
					continue;
				k = strLine.indexOf(':');
				if(k<1)
				{
					ERR("file format error!");
					return false;
				}
				strFirst = strLine.substring(0,k);
				strLast = strLine.substring(k+1);
				if(strFirst.compareTo(PACK_NAME) == 0)
				{
					// bat dau 1 pack
					nbPack++;
					packageNames[nbPack] = strLast;
					nbFile = 0;
				}
				else if(strFirst.compareTo(PACK_FILE) == 0)
				{
					// bat dau doc file cua pack
					nbFileEachPack[nbPack]++;
					files[nbPack][nbFile] = strLast;
					nbFile++;
				}
				else
				{
					LOG("...");
				}
			}
			nbPack++;
			return true;
		}catch(Exception ex)
		{
			ERR("LoadInfo()...");
			LOG(ex.toString());
			return false;
		}
	}
	static void printInfo()
	{
		LOG("\nNumber of Pack: "+nbPack);
		for(int i=0; i<nbPack; i++)
		{
			LOG("Pack "+(i+1)+": ["+packageNames[i]+"]");
			LOG("	Number of files: "+nbFileEachPack[i]);
			for(int j=0; j<nbFileEachPack[i]; j++)
			{
				LOG("		"+files[i][j]);
			}
		}
	}
	static boolean Pack()
	{
		String packageFileName;
		FileOutputStream out = null;
		int sizeOfPack = 0;
		try
		{
			for(int i=0; i<nbPack; i++)
			{
				sizeOfPack=0;
				packageFileName = outDir+packageNames[i];
				LOG("\n>>> Packing package "+(i+1)+": "+packageNames[i]);
				File f = new File(packageFileName);
				out = new FileOutputStream(f);
				if(out == null)
				{
					ERR("OutputStream is null!");
				}
				Write32(out, nbFileEachPack[i]);
				int size;
				byte[] buffer = null;
				String fileName;
				for(int j=0; j<nbFileEachPack[i]; j++)
				{
					fileName = inDir+files[i][j];
					LOG("	+Loading "+fileName);
					FileInputStream is = new FileInputStream(fileName);
					if(is == null)
					{
						ERR("InputStream is null");
					}
					size = is.available();
					buffer = new byte[size];
					is.read(buffer);
					Write32(out, size);
					out.write(buffer, 0, size);
					is.close();
					sizeOfPack+=size;
				}
				out.close();
				sizeOfPack += 4*nbFileEachPack[i] + 4;
				LOG("	 ...Size of pack: " +sizeOfPack);
			}
			
			return true;
		}
		catch(Exception ex)
		{
			LOG("Pack()...");
			ERR(ex.toString());
			return false;
		}
	}
	public static void main(String[] args)
	{
		try{
			inDir = args[0];
			outDir = args[1];
			iniFile = args[2];
			
			if(!inDir.endsWith("\\"))
				inDir += "\\";
			if(!outDir.endsWith("\\"))
				outDir += "\\";
			
			LOG("Input Dir: "+inDir);
			LOG("Output Dir: "+outDir);
		}catch(Exception ex)
		{
			LOG("main()...");
			ERR(ex.toString());
		}
		LoadInfo();
		Pack();
		// LoadPack(outDir+"EN");
	}
}